package api

import (
	"time"
	"math/big"
	"kumachan/standalone/rx"
	"kumachan/standalone/rpc"
	"kumachan/standalone/util"
	"kumachan/interpreter/runtime/lib/librpc"
	"kumachan/interpreter/runtime/rt"
)


func rpcAdaptServerOptions(opts rt.TupleValue) librpc.ServerOptions {
	return librpc.ServerOptions {
		CommonOptions: rpcAdaptCommonOptions(opts.Elements[0].(rt.TupleValue)),
	}
}
func rpcAdaptClientOptions(opts rt.TupleValue) librpc.ClientOptions {
	return librpc.ClientOptions {
		CommonOptions: rpcAdaptCommonOptions(opts.Elements[0].(rt.TupleValue)),
	}
}
func rpcAdaptCommonOptions(opts rt.TupleValue) librpc.CommonOptions {
	var log = opts.Elements[0].(rt.TupleValue)
	var log_enabled = rt.FromBool(log.Elements[0].(rt.EnumValue))
	var limits = rpcAdaptLimitOptions(opts.Elements[1].(rt.TupleValue))
	return librpc.CommonOptions {
		LogEnabled: log_enabled,
		Limits:     limits,
	}
}
func rpcAdaptLimitOptions(opts rt.TupleValue) rpc.Limits {
	var ms = func(v rt.Value) time.Duration {
		var n = v.(*big.Int)
		return (time.Millisecond * time.Duration(util.GetUintNumber(n)))
	}
	return rpc.Limits {
		SendTimeout:       ms(opts.Elements[0]),
		RecvTimeout:       ms(opts.Elements[1]),
		RecvInterval:      ms(opts.Elements[2]),
		RecvMaxObjectSize: util.GetUintNumber(opts.Elements[3].(*big.Int)),
	}
}

func __RpcServerCleartextNet(network string, addr string) librpc.ServerBackend {
	return librpc.ServerCleartextNet {
		Network: network,
		Address: addr,
	}
}
func __RpcClientCleartextNet(network string, addr string) librpc.ClientBackend {
	return librpc.ClientCleartextNet {
		Network: network,
		Address: addr,
	}
}
func __RpcConnectionClose(conn rpc.Connection) rx.Observable {
	return rx.NewSync(func() (rx.Object, bool) {
		_ = conn.Close()
		return nil, true
	})
}
func __RpcConnectionOnClose(conn rpc.Connection) rx.Observable {
	return conn.OnClose()
}
func __RpcServe (
	id        rpc.ServiceIdentifier,
	backend   librpc.ServerBackend,
	raw_opts rt.TupleValue,
	ctor rt.Value,
	h rt.InteropContext,
) rx.Observable {
	var api = h.RpcApi()
	var opts = rpcAdaptServerOptions(raw_opts)
	var wrapped_ctor = func(arg rt.Value, conn rpc.Connection) rx.Observable {
		var pair = rt.Tuple(arg, conn)
		return h.Call(ctor, pair).(rx.Observable)
	}
	return librpc.Serve(id, api, backend, opts, wrapped_ctor)
}
func __RpcAccess (
	id        rpc.ServiceIdentifier,
	backend   librpc.ClientBackend,
	raw_opts rt.TupleValue,
	argument rt.Value,
	consumer rt.Value,
	h rt.InteropContext,
) rx.Observable {
	var api = h.RpcApi()
	var opts = rpcAdaptClientOptions(raw_opts)
	var wrapped_consumer = func(instance rt.Value) rx.Observable {
		return h.Call(consumer, instance).(rx.Observable)
	}
	return librpc.Access(id, api, backend, opts, argument, wrapped_consumer)
}


